package com.faya.green.service.impl;

import com.faya.green.abnormal.ServiceException;
import com.faya.green.common.Constant;
import com.faya.green.dao.user.RelationshipDao;
import com.faya.green.dao.user.SubsidiaryUserDao;
import com.faya.green.dao.user.UserDao;
import com.faya.green.enumeration.StatusEnum;
import com.faya.green.model.Relationship;
import com.faya.green.model.SubsidiaryUser;
import com.faya.green.model.User;
import com.faya.green.service.SubsidiaryUserService;
import com.faya.green.utils.CommonUtils;
import com.faya.green.utils.FileUtils;
import com.faya.green.utils.ImgUtils;
import com.faya.green.utils.PropertiesUtil;
import com.google.gson.Gson;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.multipart.MultipartFile;

import javax.servlet.http.HttpServletRequest;
import java.io.File;
import java.io.IOException;
import java.util.*;

/**
 * @author ：LX
 * 创建时间： 2018/8/25. 0:42
 * 地点：广州
 * 目的: 隶属主用户的子用户数据（主用户的私人关系，没有任何权限）
 * 备注说明：
 */
@Service
public class SubsidiaryUserServiceImpl implements SubsidiaryUserService {

    //压制全部警告
    @SuppressWarnings("all")
    @Autowired
    private SubsidiaryUserDao subsidiaryUserDao;
    //压制全部警告
    @SuppressWarnings("all")
    @Autowired
    private RelationshipDao relationshipDao;
    //压制全部警告
    @SuppressWarnings("all")
    @Autowired
    private UserDao userDao;

    @Override
    public void updateSubsidiaryUser(SubsidiaryUser subsidiaryUser) {
        subsidiaryUserDao.updateSubsidiaryUser(subsidiaryUser);
    }


    @Override
    public SubsidiaryUser getSubsidiaryUserById(String id) {
        return subsidiaryUserDao.getSubsidiaryUserById(id);
    }

    @Transactional(rollbackFor = Exception.class)
    @Override
    public void addOrUpdSubsidiaryUser(MultipartFile file, SubsidiaryUser subsidiaryUser, Relationship relationship, HttpServletRequest request) {
        //数据校验
        if (CommonUtils.checkNull(relationship.getLevel())){
            throw new ServiceException("用户关系不能为空");
        }
        if (CommonUtils.checkNull(relationship.getFather())){
            throw new ServiceException("父节点不能为空");
        }
        if (CommonUtils.checkNull(subsidiaryUser.getName())){
            throw new ServiceException("名字不能为空");
        }

        // 新增
        if (CommonUtils.checkNull(subsidiaryUser.getId())){
            User user = userDao.findUserById(relationship.getFather());
            if (user != null){
                //说明主用户在添加子用户
                user.setIsRelation(Constant.YES);
                userDao.updateUser(user);
            }
            imgHandle(file, subsidiaryUser, request, "add");

            subsidiaryUser.setId(UUID.randomUUID().toString());
            subsidiaryUser.setCreateTime(new Date());
            subsidiaryUser.setStatus(StatusEnum.STATUS_ADD.getCode());
            subsidiaryUser.setUpdateTime(new Date());
            subsidiaryUserDao.addSubsidiaryUser(subsidiaryUser);

            relationship.setId(UUID.randomUUID().toString());
            relationship.setSon(subsidiaryUser.getId());
            relationship.setDstate(StatusEnum.STATUS_ADD.getCode());
            relationship.setCreateDate(new Date());
            relationship.setUpdateDate(new Date());
            relationshipDao.addRelationship(relationship);

        } else {
            //修改
            imgHandle(file, subsidiaryUser, request, "upd");

            subsidiaryUser.setStatus(StatusEnum.STATUS_UPDATE.getCode());
            subsidiaryUser.setUpdateTime(new Date());
            subsidiaryUserDao.updateSubsidiaryUser(subsidiaryUser);

            relationship.setSon(subsidiaryUser.getId());
            relationship.setDstate(StatusEnum.STATUS_UPDATE.getCode());
            relationship.setUpdateDate(new Date());
            relationshipDao.updateRelationship(relationship);

        }



    }

    /**
     * 图片的处理
     * @param file 图片文件
     * @param subsidiaryUser 子用户
     * @param updOrAdd 修改还是新增 upd 修改 add 新增
     */
    private void imgHandle(MultipartFile file, SubsidiaryUser subsidiaryUser, HttpServletRequest request, String updOrAdd){
        //file.getSize 获取文件的大小，没有则是0，  isEmpty 判空，如果是空则为true
        if (file != null && file.getSize() > 0 && !file.isEmpty()){
            try {
                String imgName = subsidiaryUserImgHandle(file);
                subsidiaryUser.setImgHred(imgName);
            } catch (IOException e) {
                e.printStackTrace();
                throw new ServiceException("机构图片上传失败");
            }
            delOldImg(updOrAdd, subsidiaryUser);

        } else {
            //如果本地上传有图片则使用本地上传的，否则查看网络的图片是否存在,存在则上传到本地
            String networkUserImg = request.getParameter("networkUserImg");
            if (!CommonUtils.checkNull(networkUserImg)){
                //返回图片名
                String imgName = null;
                try {
                    imgName = ImgUtils.downImgLoad(networkUserImg);
                } catch (Exception e) {
                    e.printStackTrace();
                    throw new ServiceException("下载网络头像图片失败");
                }
                if (!CommonUtils.checkNull(imgName)){
                    String imgDownTemp = PropertiesUtil.getConfigValue("imgDownTemp");
                    String imgNamePath = imgDownTemp + imgName;
                    File fileImg = new File(imgNamePath);

                    String imgHredSize = PropertiesUtil.getConfigValue("subsidiaryUserImgSize");
                    if (fileImg.length() > Integer.valueOf(imgHredSize)){
                        //删除临时文件
                        FileUtils.delectFile(imgNamePath);
                        throw new ServiceException("网络图片大小超过最大限制");
                    }

                    String imgHred = PropertiesUtil.getConfigValue("subsidiaryUserImg");
                    try {
                        FileUtils.copyFileUsingFileChannels(fileImg, new File(imgHred + imgName));
                    } catch (IOException e) {
                        e.printStackTrace();
                        //删除临时文件
                        FileUtils.delectFile(imgNamePath);
                        throw new ServiceException("网络图片复制失败");
                    }

                    subsidiaryUser.setImgHred(imgName);
                    //删除临时文件
                    FileUtils.delectFile(imgNamePath);

                    delOldImg(updOrAdd, subsidiaryUser);
                }
            }
        }

    }

    /**
     * 对旧图片进行处理
     * @param updOrAdd 是更新还是新增
     * @param subsidiaryUser 子用户
     */
    private void delOldImg(String updOrAdd, SubsidiaryUser subsidiaryUser){
        //是更新的话要清除掉旧图片
        if ("upd".equals(updOrAdd)){
            String id = subsidiaryUser.getId();
            SubsidiaryUser sub = subsidiaryUserDao.getSubsidiaryUserById(id);
            if (sub == null){
                throw new ServiceException("未找到待修改用户");
            }
            String imgHred = sub.getImgHred();
            String imgPath = PropertiesUtil.getConfigValue("subsidiaryUserImg");
            String path = imgPath + imgHred;
            FileUtils.delectFile(path);
        }
    }


    /**
     * 对子用户的图片处理
     * @param file 图片
     * @return  name 图片名字
     */
    private String subsidiaryUserImgHandle(MultipartFile file) throws IOException {
        //获得图片文件名包括后缀
        String imgName = file.getOriginalFilename();
        //获取后缀（总后开始找.获得下标）
        String prefix = imgName.substring(imgName.lastIndexOf(".") + 1);
        //转换为小写
        prefix = prefix.toLowerCase();
        if (!ImgUtils.checkImgSuffix(file)){
            throw new ServiceException("图片格式有误");
        }

        String imgHredSize = PropertiesUtil.getConfigValue("subsidiaryUserImgSize");
        if (file.getSize() > Integer.valueOf(imgHredSize)){
            throw new ServiceException("上传图片超过大小限制，请重新上传");
        }

        //新的图片名字 + 后缀
        String newImgName = ImgUtils.newImgName();
        String name = newImgName + "." + prefix;
        //组合成路径
        String imgHred = PropertiesUtil.getConfigValue("subsidiaryUserImg");
        FileUtils.init(imgHred);

        //图片处理
        ImgUtils.imgZip(prefix, file, imgHred, name, 75, 75);
        return name;
    }


    @Override
    public SubsidiaryUser getUserRelattionship(String userId){
        //先查询到要获取关系数据的用户
        User userCore = userDao.findUserById(userId);
        //先转换为SubsidiaryUser用户
        SubsidiaryUser subsidiaryUser = new SubsidiaryUser();
        subsidiaryUser.setId(userCore.getId());
        subsidiaryUser.setName(userCore.getName());
        subsidiaryUser.setSex(userCore.getSex());
        subsidiaryUser.setBirthday(userCore.getBirthday());
        subsidiaryUser.setEthnic(userCore.getEthnic());
        subsidiaryUser.setProvince(userCore.getProvince());
        subsidiaryUser.setCity(userCore.getCity());
        subsidiaryUser.setCounty(userCore.getCounty());
        subsidiaryUser.setAddDetails(userCore.getAddDetails());
        subsidiaryUser.setSchool(userCore.getSchool());
        subsidiaryUser.setProfession(userCore.getProfession());
        subsidiaryUser.setImgHred(userCore.getImgHred());
        subsidiaryUser.setEmail(userCore.getEmail());
        subsidiaryUser.setIsParty(userCore.getIsParty());
        subsidiaryUser.setAddParty(userCore.getAddParty());
        subsidiaryUser.setCreateTime(userCore.getCreateTime());
        subsidiaryUser.setUpdateTime(userCore.getUpdateTime());
        subsidiaryUser.setStatus(userCore.getStatus());
        subsidiaryUser.setRemark(userCore.getRemark());

        Map map = new HashMap<>();
        map.put("userCore", subsidiaryUser);
        SubsidiaryUser userListSon = getSonNodeTwo(map);
        return userListSon;
    }

    /**
     * 删除会将他的全部下级也一起删除
     * @param id 子用户ID
     */
    @Transactional(rollbackFor = Exception.class)
    @Override
    public void delSubsidiaryUser(String id) {
        User user = userDao.findUserById(id);
        if (user != null){
            throw new ServiceException("主用户不能删除");
        }

        SubsidiaryUser subsidiaryUser = subsidiaryUserDao.getSubsidiaryUserById(id);
        if (subsidiaryUser == null){
            throw new ServiceException("找不到对应子用户");
        }
        //拿到关系
        Relationship relationship = relationshipDao.getRelationshipBySon(subsidiaryUser.getId());
        if (relationship == null){
            throw new ServiceException("获取用户关系失败");
        }

        Map map = new HashMap<>();
        map.put("userCore", subsidiaryUser);
        SubsidiaryUser userListSon = getSonNodeTwo(map);

        //保存关系ID
        List<String> relationShipIdList = new ArrayList<>();
        //保存子用户ID
        List<String> subsidiaryUserList = new ArrayList<>();
        //图片
        List<String> imgList = new ArrayList<>();

        relationShipIdList.add(relationship.getId());

        Map<String, Object> mapData = new HashMap(3);
        mapData.put("relationShipIdList", relationShipIdList);
        mapData.put("subsidiaryUserList", subsidiaryUserList);
        mapData.put("imgList", imgList);

        //将数据解析放到list中
        Map m = getAllData(mapData, userListSon);
        List<String> rIdList = (List<String>)m.get("relationShipIdList");
        List<String> sUserList = (List<String>)m.get("subsidiaryUserList");
        List<String> iList = (List<String>)m.get("imgList");

        //执行删除操作
        for (String relationShipId : rIdList){
            relationshipDao.delRelationshipById(relationShipId);
        }
        for (String suserId : sUserList){
            subsidiaryUserDao.delSubsidiaryUserById(suserId);
        }
        //最后才执行删除图片操作，图片删除是无法恢复的
        String imgBasePath = PropertiesUtil.getConfigValue("subsidiaryUserImg");
        for (String img : iList){
            FileUtils.delectFile(imgBasePath + img);
        }
    }


    /***
     * 解析数据
     * @param map map集合
     * @param userListSon 要解析的数据
     * @return
     */
    private Map getAllData(Map map, SubsidiaryUser userListSon){
        List<String> relationShipIdList = (List<String>)map.get("relationShipIdList");
        List<String> subsidiaryUserList = (List<String>)map.get("subsidiaryUserList");
        List<String> imgList = (List<String>)map.get("imgList");
        if (userListSon != null){
            String relationshipId = userListSon.getRelationshipId();
            if (!CommonUtils.checkNull(relationshipId)){
                relationShipIdList.add(relationshipId);
            }
            String userListSonId = userListSon.getId();
            if (!CommonUtils.checkNull(userListSonId)){
                subsidiaryUserList.add(userListSonId);
            }
            String imgHred = userListSon.getImgHred();
            if (!CommonUtils.checkNull(imgHred)){
                imgList.add(imgHred);
            }

            if (userListSon.getChildren() != null && userListSon.getChildren().size() > 0){
                for (SubsidiaryUser subsidiaryUser : userListSon.getChildren()){
                    getAllData(map, subsidiaryUser);
                }
            }
        }
        return map;
    }


    /**
     * 获取全部的son节点并且包含关系
     * @param map userList 全部保存的用户以及节点信息  id 用户id
     *            user 中保存了user，而当前的user保存的关系是与上一级的user的关机，当前的user的id在关系中是son，上一级的是父节点
     * @return
     */
    private SubsidiaryUser getSonNodeTwo(Map map){
        SubsidiaryUser userCore = (SubsidiaryUser)map.get("userCore");

        //查询此节点下面的所有的子节点（根据父节点找），根据父节点可以查询到这个父节点下全部的子节点
        List<Relationship> relationships = relationshipDao.getRelationshipByFather(userCore.getId());
        List list = new ArrayList<User>();

        //遍历查询到的全部子节点
        for (int i = 0; i < relationships.size(); i ++){
            Relationship relationship = relationships.get(i);
            if (relationship != null){
                //将当前节点与上级节点的关系保存在这个user中.根据子节点查询只能查询到唯一的父级（设计如此），该关系即两者的关系
                Relationship levelBySon = relationshipDao.getRelationshipBySon(relationship.getSon());
                SubsidiaryUser subsidiaryUser = subsidiaryUserDao.getSubsidiaryUserById(relationship.getSon());
                if (levelBySon != null){
                    subsidiaryUser.setTitle(levelBySon.getExplain());
                    subsidiaryUser.setClassName(levelBySon.getLevel());
                    subsidiaryUser.setRelationshipId(levelBySon.getId());
                }
                list.add(subsidiaryUser);
                userCore.setChildren(list);
                //封装
                Map m = new HashMap();
                m.put("userCore", subsidiaryUser);
                //递归操作
                getSonNodeTwo(m);
            }
        }

        return userCore;
    }
}
